package com.gome.gop.util.export;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletOutputStream;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.xmind.core.Core;
import org.xmind.core.CoreException;
import org.xmind.core.ISheet;
import org.xmind.core.ITopic;
import org.xmind.core.IWorkbook;
import org.xmind.core.IWorkbookBuilder;

/**
 * @author 悠悠做神仙
 * @version 1.0.0
 * @ProjectName yyzsxDemo
 * @ClassName CreateXmind.java
 * @Description TODO
 * @createTime 2021年08月26日 18:32:00
 */
public class XmindUtils {
    
    public static void main(String[] args)
        throws CoreException, IOException {
        System.out.println(StringUtils.equals(null, null));
        // String root = "演示脑图";
        ////// String xmindPath = "./demo.xmind";
        ////// XmindUtils xmindUtils = new XmindUtils();
        ////// xmindUtils.createXmind(root, xmindPath);
    }
    
    public void createXmind(String root, String path)
        throws CoreException, IOException {
        // 创建思维导图的工作空间
        IWorkbookBuilder workbookBuilder = Core.getWorkbookBuilder();
        IWorkbook workbook = workbookBuilder.createWorkbook();
        // 获得默认sheet
        ISheet primarySheet = workbook.getPrimarySheet();
        // 获得根主题
        ITopic rootTopic = primarySheet.getRootTopic();
        // 设置根主题的标题
        rootTopic.setTitleText(root);
        // 正确的逻辑图 org.xmind.ui.logic.right
        rootTopic.setStructureClass("org.xmind.ui.logic.right");
        // 创建所有节点的集合
        // ArrayList<ITopic> chapterTopics = obtainTopic(workbook, null);
        ArrayList<ITopic> chapterTopics = new ArrayList<>();
        // 把所有一级节点都加到根节点上
        chapterTopics.forEach(it -> rootTopic.add(it, ITopic.ATTACHED));
        workbook.save(path);
    }
    
    private static ITopic doMergeRegion(IWorkbook workbook, ITopic parentTopic, List<List<String>> exportLines, ExportFile.Region region) {
        
        if (region == null) {
            return parentTopic;
        }
        StringBuilder stringBuilder = new StringBuilder();
        Integer columnEnd = region.getColumnEnd() + 1;
        for (Integer column = region.getColumnStart(); column <= columnEnd; column++) {
            if (column % 2 == 0) {
                append(stringBuilder, obtainCellValue(exportLines, region.getRowStart(), column));
                continue;
            }
            for (java.lang.Integer row = region.getRowStart(); row <= region.getRowEnd(); row++) {
                append(stringBuilder, obtainCellValue(exportLines, row, column));
            }
        }
        ITopic topic = workbook.createTopic();
        topic.setTitleText(stringBuilder.toString());
        parentTopic.add(topic);
        region.setMerged(true);
        return topic;
        
    }
    
    private static void append(StringBuilder stringBuilder, String obtainCellValue) {
        if (StringUtils.isNotBlank(obtainCellValue)) {
            stringBuilder.append(obtainCellValue);
            stringBuilder.append("\r\n");
        }
        
    }
    
    private static String obtainCellValue(List<List<String>> exportLines, int line, Integer column) {
        
        String cell = obtainCell(exportLines, line, column);
        if (StringUtils.isNotBlank(cell)) {
            return cell;
        }
        return null;
    }
    
    private static String obtainCell(List<List<String>> exportLines, int line, Integer column) {
        
        if (notExistCell(exportLines, line, column)) {
            return null;
        }
        return exportLines.get(line).get(column);
        
    }
    
    private static boolean notExistCell(List<List<String>> exportLines, int lineNo, Integer columnNo) {
        return !existCell(exportLines, lineNo, columnNo);
        
    }
    
    private static boolean existCell(List<List<String>> exportLines, int lineNo, Integer columnNo) {
        
        if (lineNo >= exportLines.size() || lineNo < 0) {
            return false;
        }
        if (columnNo >= exportLines.get(lineNo).size() || columnNo < 0) {
            return false;
        }
        return true;
        
    }
    
    private static ITopic obtainTopic(int i, IWorkbook workbook, Boolean hasSub) {
        ITopic topic = workbook.createTopic();
        topic.setTitleText("第一个，一级节点" + i + hasSub);
        if (hasSub != null && hasSub) {
            topic.add(obtainTopic(i, workbook, false));
        }
        return topic;
    }
    
    public static void export(ExportFile exportFile, ServletOutputStream outputStream)
        throws IOException, CoreException {
        IWorkbookBuilder workbookBuilder = Core.getWorkbookBuilder();
        IWorkbook workbook = workbookBuilder.createWorkbook();
        createSheet(exportFile, workbook);
        removeEmptySheet(workbook);
        workbook.save(outputStream);
        
    }
    
    private static void removeEmptySheet(IWorkbook workbook) {
        if (workbook == null || CollectionUtils.isEmpty(workbook.getSheets())) {
            return;
        }
        for (ISheet sheet : workbook.getSheets()) {
            if (sheet == null) {
                continue;
            }
            if (StringUtils.isBlank(sheet.getTitleText()) && CollectionUtils.isEmpty(sheet.getRootTopic().getAllChildren())) {
                workbook.removeSheet(sheet);
            }
        }
    }
    
    private static void createSheet(ExportFile exportFile, IWorkbook workbook) {
        
        if (exportFile == null || CollectionUtils.isEmpty(exportFile.getExportSheetList())) {
            return;
        }
        for (ExportSheet exportSheet : exportFile.getExportSheetList()) {
            createSheetMain(exportSheet, workbook);
        }
        
    }
    
    private static void createSheetMain(ExportSheet exportSheet, IWorkbook workbook) {
        
        if (exportSheet == null) {
            return;
        }
        ISheet sheet = null;
        if (StringUtils.isBlank(workbook.getPrimarySheet().getTitleText())) {
            sheet = workbook.getPrimarySheet();
        }
        if (StringUtils.isNotBlank(workbook.getPrimarySheet().getTitleText())) {
            sheet = workbook.createSheet();
        }
        sheet.setTitleText(exportSheet.getName());
        resetSheet(workbook, sheet, exportSheet);
        workbook.addSheet(sheet);
        
    }
    
    private static void resetSheet(IWorkbook workbook, ISheet sheet, ExportSheet exportSheet) {
        
        ITopic rootTopic = sheet.getRootTopic();
        rootTopic.setTitleText(exportSheet.getName());
        rootTopic.setStructureClass("org.xmind.ui.logic.right");
        mergeRegion(workbook, rootTopic, exportSheet.getExportLines(), null);
        
    }
    
    private static void mergeRegion(IWorkbook workbook, ITopic parentTopic, List<List<String>> exportLines, ExportFile.Region regionPrevious) {
        
        Integer lineStart = null;
        Integer lineEnd = null;
        Integer column = null;
        if (regionPrevious == null) {
            lineStart = 0;
            lineEnd = exportLines.size() - 1;
            column = 2;
        }
        if (regionPrevious != null) {
            lineStart = regionPrevious.getRowStart();
            lineEnd = regionPrevious.getRowEnd();
            column = regionPrevious.getColumnEnd() + 2;
        }
        ITopic newTopic = null;
        for (Integer lineNo = lineStart; lineNo <= lineEnd; lineNo++) {
            ExportFile.Region region = new ExportFile.Region(lineStart, lineNo, column, column);
            addRegion(workbook, parentTopic, exportLines, regionPrevious, region);
            boolean isAddBranch = isAddBranch(exportLines, regionPrevious, region);
            if (isAddBranch && newTopic == null) {
                newTopic = obtainNewTopic(newTopic, workbook, parentTopic, regionPrevious, exportLines);
            }
            if (isAddBranch && isNotEmpty(exportLines, region)) {
                mergeRegion(workbook, newTopic, exportLines, region);
            }
            if (isAddBranch) {
                lineStart = lineNo + 1;
            }
        }
        
    }
    
    private static boolean isNotEmpty(List<List<String>> exportLines, ExportFile.Region region) {
        
        return StringUtils.isNotBlank(obtainCurrent(region, exportLines));
        
    }
    
    private static boolean isAddBranch(List<List<String>> exportLines, ExportFile.Region regionPrevious, ExportFile.Region region) {
        
        Integer rowStart = null;
        if (regionPrevious != null) {
            rowStart = regionPrevious.getRowStart();
        }
        if (regionPrevious == null) {
            rowStart = 0;
        }
        Integer rowEnd = null;
        if (regionPrevious != null) {
            rowEnd = regionPrevious.getRowEnd();
        }
        if (regionPrevious == null) {
            rowEnd = exportLines.size() - 1;
        }
        if (StringUtils.isBlank(obtainCurrent(region, exportLines))) {
            return true;
        }
        // 除最后一行,所有需要跟下边比较
        if (region.getRowEnd() < rowEnd && !StringUtils.equals(obtainCurrent(region, exportLines), obtainBelow(region, exportLines))) {
            return true;
        }
        // 最后一行不需要跟下边比较
        if (region.getRowEnd().equals(rowEnd) && !region.getRowStart().equals(rowStart)) {
            return true;
        }
        return false;
    }
    
    private static String obtainCurrent(ExportFile.Region region, List<List<String>> exportLines) {
        
        return obtainCellValue(exportLines, region.getRowEnd(), region.getColumnEnd());
        
    }
    
    private static String obtainBelow(ExportFile.Region region, List<List<String>> exportLines) {
        
        return obtainCellValue(exportLines, region.getRowEnd() + 1, region.getColumnEnd());
        
    }
    
    private static ITopic obtainNewTopic(ITopic newTopic, IWorkbook workbook, ITopic parentTopic, ExportFile.Region region, List<List<String>> exportLines) {
        
        if (newTopic != null) {
            return newTopic;
        }
        ITopic topic = workbook.createTopic();
        topic.setTitleText(obtainText(exportLines, region));
        parentTopic.add(topic);
        return topic;
        
    }
    
    private static String obtainText(List<List<String>> exportLines, ExportFile.Region region) {
        
        if (CollectionUtils.isEmpty(exportLines) || region == null) {
            return null;
        }
        StringBuilder stringBuilder = new StringBuilder();
        Integer columnEnd = region.getColumnEnd() + 1;
        for (Integer column = region.getColumnStart(); column <= columnEnd; column++) {
            if (column % 2 == 0) {
                append(stringBuilder, obtainCellValue(exportLines, region.getRowStart(), column));
                continue;
            }
            for (java.lang.Integer row = region.getRowStart(); row <= region.getRowEnd(); row++) {
                append(stringBuilder, obtainCellValue(exportLines, row, column));
            }
        }
        return stringBuilder.toString();
        
    }
    
    private static void addRegion(IWorkbook workbook, ITopic parentTopic, List<List<String>> exportLines, ExportFile.Region regionPrevious, ExportFile.Region region) {
        
        if (regionPrevious == null && region.getRowStart().equals(0) && region.getRowEnd().equals(exportLines.size() - 1)) {
            mergeRegion(workbook, parentTopic, exportLines, region);
            return;
        }
        if (regionPrevious == null) {
            return;
        }
        if (StringUtils.isNotBlank(obtainCurrent(region, exportLines)) && regionPrevious.getRowStart().equals(region.getRowStart())
            && regionPrevious.getRowEnd().equals(region.getRowEnd())) {
            region.setColumnStart(regionPrevious.getColumnStart());
            mergeRegion(workbook, parentTopic, exportLines, region);
            return;
        }
        
    }
    
    private static void forwardToRight(IWorkbook workbook, ITopic parentTopic, List<List<String>> exportLines, ExportFile.Region regionPrevious, ExportFile.Region region) {
        
        // 与前边的行一样,与前边合并向右推进
        if (regionPrevious != null && region != null && regionPrevious.getRowStart().equals(region.getRowStart())
            
            && regionPrevious.getRowEnd().equals(region.getRowEnd())) {
            
            region.setColumnStart(regionPrevious.getColumnStart());
            mergeRegion(workbook, parentTopic, exportLines, region);
            return;
        }
        // 与前边不一样,合并前边
        ITopic parentTopicNew = doMergeRegion(workbook, parentTopic, exportLines, regionPrevious);
        // 与前边不一样,新的项目向前推进
        mergeRegion(workbook, parentTopicNew, exportLines, region);
        
    }
    
}